﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace EasyNet.Componets.Core.Http
{
    public class EasyNetHttpClient : IHttpClient
    {
        #region Get
        public string Get(string url, Encoding encoding, Dictionary<string, string> headerList,
            ref CookieContainer cookieContainer)
        {
            if (encoding == null)
            {
                encoding = Encoding.UTF8;
            }
            var request = CreateRequest(url, HttpMethod.Get, null, null, encoding, headerList, cookieContainer);
   
            using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
            using (var streamReader = new StreamReader(response.GetResponseStream(), encoding ?? Encoding.UTF8))
            {
                if (response.Cookies != null && response.Cookies.Count > 0)
                {
                    cookieContainer.Add(response.Cookies);
                }

                return streamReader.ReadToEnd();
            }
        }

        public async Task<string> GetAsync(string url, Encoding encoding, Dictionary<string, string> headerList,
            CookieContainer cookieContainer)
        {
            if (encoding == null)
            {
                encoding = Encoding.UTF8;
            }
            var request = CreateRequest(url, HttpMethod.Get, null, null, encoding, headerList, cookieContainer);

            using (WebResponse response = await request.GetResponseAsync())
            using (var streamReader = new StreamReader(response.GetResponseStream(), encoding ?? Encoding.UTF8))
            {
                try
                {
                    if (response is HttpWebResponse)
                    {
                        var httpResponse = response as HttpWebResponse;
                        if (httpResponse.Cookies != null && httpResponse.Cookies.Count > 0)
                        {
                            cookieContainer.Add(httpResponse.Cookies);
                        }
                    }
                }
                catch
                {

                }

                return streamReader.ReadToEnd();
            }
        }
        #endregion

        #region Post
        public string Post(string url, string body, string contentType, Encoding encoding,
            Dictionary<string, string> headerList, ref CookieContainer cookieContainer)
        {
            if (encoding == null)
            {
                encoding = Encoding.UTF8;
            }
            var request = CreateRequest(url, HttpMethod.Post, contentType, body, encoding, headerList, cookieContainer);

            using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
            using (var streamReader = new StreamReader(response.GetResponseStream(), encoding))
            {
                if (response.Cookies != null && response.Cookies.Count > 0)
                {
                    cookieContainer.Add(response.Cookies);
                }
                return streamReader.ReadToEnd();
            }
        }

        public async Task<string> PostAsync(string url, string body, string contentType, Encoding encoding,
            Dictionary<string, string> headerList, CookieContainer cookieContainer)
        {
            if (encoding == null)
            {
                encoding = Encoding.UTF8;
            }
            var request = CreateRequest(url, HttpMethod.Post, contentType, body, encoding, headerList, cookieContainer);

            using (WebResponse response = await request.GetResponseAsync())
            using (var streamReader = new StreamReader(response.GetResponseStream(), encoding))
            {
                try
                {
                    if (response is HttpWebResponse)
                    {
                        var httpResponse = response as HttpWebResponse;
                        if (httpResponse.Cookies != null && httpResponse.Cookies.Count > 0)
                        {
                            cookieContainer.Add(httpResponse.Cookies);
                        }
                    }
                }
                catch
                {

                }

                return streamReader.ReadToEnd();
            }
        }

        #endregion

        #region Private
        private HttpWebRequest CreateRequest(string url, string method, string contentType, string body,
            Encoding encoding, Dictionary<string, string> headerList, CookieContainer cookieContainer)
        {
            if (encoding == null)
            {
                encoding = Encoding.UTF8;
            }
            byte[] buffer = !body.IsNullOrEmpty() ? encoding.GetBytes(body) : new byte[0];
            var request = (HttpWebRequest)WebRequest.Create(url);
            request.Method = method;
            if (!string.IsNullOrEmpty(contentType))
            {
                request.ContentType = contentType;
            }

            request.ContentLength = buffer.Length;
            //添加header
            if (headerList != null && headerList.Count > 0)
            {
                foreach (var item in headerList)
                {
                    request.Headers.Add(item.Key, item.Value);
                }
            }
            //设置cookie
            if (cookieContainer == null)
            {
                cookieContainer = new CookieContainer();
            }
            request.CookieContainer = cookieContainer;

            if (buffer.Length > 0)
            {
                using (Stream requestStream = request.GetRequestStream())
                {
                    requestStream.Write(buffer, 0, buffer.Length);
                }
            }
            var timeOut = System.Configuration.ConfigurationManager.AppSettings["Http_Request_TimeOut"];
            if(!string.IsNullOrEmpty(timeOut))
            {
                request.Timeout = int.Parse(timeOut) * 1000;
            }

            return request;
        }
        #endregion

        #region Delete
        public string Delete(string url, Encoding encoding, Dictionary<string, string> headerList, ref CookieContainer cookieContainer)
        {
            if (encoding == null)
            {
                encoding = Encoding.UTF8;
            }
            var request = CreateRequest(url, HttpMethod.Delete, null, null, encoding, headerList, cookieContainer);

            using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
            using (var streamReader = new StreamReader(response.GetResponseStream(), encoding ?? Encoding.UTF8))
            {
                if (response.Cookies != null && response.Cookies.Count > 0)
                {
                    cookieContainer.Add(response.Cookies);
                }

                return streamReader.ReadToEnd();
            }
        }
        #endregion

        #region Update
        public string Update(string url, string body, string contentType, Encoding encoding,
            Dictionary<string, string> headerList, ref CookieContainer cookieContainer)
        {
            if (encoding == null)
            {
                encoding = Encoding.UTF8;
            }
            var request = CreateRequest(url, HttpMethod.Put, contentType, body, encoding, headerList, cookieContainer);
            
            using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
            using (var streamReader = new StreamReader(response.GetResponseStream(), encoding))
            {
                if (response.Cookies != null && response.Cookies.Count > 0)
                {
                    cookieContainer.Add(response.Cookies);
                }
                return streamReader.ReadToEnd();
            }
        }
        #endregion

    }
}
